package com.sino.dataworks.datasource;

import cn.hutool.core.collection.ConcurrentHashSet;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.dataworks_public.model.v20200518.ListDataSourcesResponse;
import com.sino.dataworks.dto.DataSourceConfig;
import com.sino.dataworks.util.DataworksUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.sino.dataworks.util.JobVarUtil.datasources;

@Component
@Slf4j
public class DynamicDataSourceLoader {

    @Autowired
    private ApplicationContext applicationContext;

    // 存储已注册的数据源名称
    private final Set<String> registeredDataSources = new ConcurrentHashSet<>();

    /**
     * 加载所有启用的数据源配置并注册为Bean
     */
   // @PostConstruct
    public void initDataSources() {
        log.info("加载数据源");
       List<DataSourceConfig> configs = new ArrayList<>();
        DataworksUtil.getDatasource();
        for (String key: datasources.keySet()){
            DataSourceConfig dataSourceConfig=new DataSourceConfig();
            ListDataSourcesResponse.Data.DataSourcesItem dataSourcesItem=datasources.get(key);
            String datasourceType=dataSourcesItem.getDataSourceType();
            if(datasourceType.equals("mysql")||datasourceType.equals("oracle")){
                JSONObject json=JSONObject.parseObject(dataSourcesItem.getContent());
                String jdbcUrl=json.getString("jdbcUrl");
                String userName=json.getString("username");
                String pwd=json.getString("password");
                dataSourceConfig.setName(dataSourcesItem.getName());
                dataSourceConfig.setUrl(jdbcUrl);
                dataSourceConfig.setUsername(userName);
                if(datasourceType.equals("oracle")){
                    dataSourceConfig.setDriverClass("oracle.jdbc.OracleDriver");
                }else if(datasourceType.equals("mysql")){
                    dataSourceConfig.setDriverClass("com.mysql.jdbc.Driver");
                }
               // dataSourceConfig.setPassword(pwd);
                configs.add(dataSourceConfig);
            }
        }
        configs.forEach(this::registerDataSource);
        log.info("已注册数据源:"+ JSON.toJSONString(registeredDataSources));
    }

    /**
     * 注册单个数据源
     */
    public void registerDataSource(DataSourceConfig config) {
        if (registeredDataSources.contains(config.getName())) {
            return; // 避免重复注册
        }

        DataSource dataSource = createDataSource(config);
        registerBean(config.getName(), dataSource);
        registeredDataSources.add(config.getName());
    }

    /**
     * 创建Druid数据源实例
     */
    private DataSource createDataSource(DataSourceConfig config) {
        DruidDataSource druidDataSource = new DruidDataSource();

        // 基础连接配置
        druidDataSource.setUrl(config.getUrl());
        druidDataSource.setUsername(config.getUsername());
        druidDataSource.setPassword(config.getPassword());
        druidDataSource.setDriverClassName(config.getDriverClass());
        druidDataSource.setName("Druid-" + config.getName()); // 连接池名称标识

        // 连接池核心参数（可扩展从配置表读取）
        druidDataSource.setInitialSize(5);         // 初始连接数
        druidDataSource.setMinIdle(5);            // 最小空闲连接
        druidDataSource.setMaxActive(20);         // 最大活跃连接
        druidDataSource.setMaxWait(60000L);       // 获取连接超时时间（毫秒）

        // 连接有效性检测
        druidDataSource.setValidationQuery("SELECT 1");
        druidDataSource.setTestWhileIdle(true);   // 空闲时检测
        druidDataSource.setTestOnBorrow(true);    // 获取连接时检测

        // 其他优化配置
        druidDataSource.setTimeBetweenEvictionRunsMillis(60000L); // 关闭空闲连接的间隔
        druidDataSource.setMinEvictableIdleTimeMillis(300000L);   // 连接保持空闲的最小时间

        try {
            druidDataSource.init(); // 初始化连接池
        } catch (SQLException e) {
            throw new RuntimeException("Druid数据源初始化失败: " + config.getName(), e);
        }

        return druidDataSource;
    }

    /**
     * 动态注册Bean至Spring容器
     */
    private void registerBean(String beanName, DataSource dataSource) {
        ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();

        BeanDefinitionBuilder builder = BeanDefinitionBuilder
                .genericBeanDefinition(DataSource.class, () -> dataSource)
                .setDestroyMethodName("close"); // Druid的close方法会释放资源

        beanFactory.registerBeanDefinition(beanName, builder.getBeanDefinition());
    }
    /**
     * 移除数据源
     */
    public void unregisterDataSource(String name) {
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
        if (beanFactory.containsBean(name)) {
            beanFactory.destroySingleton(name);
            beanFactory.removeBeanDefinition(name);
            registeredDataSources.remove(name);
        }
    }
}